/* Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.yzbdl.lanius.orchestrate.serv.service.system.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yzbdl.lanius.orchestrate.serv.dto.system.*;
import org.yzbdl.lanius.orchestrate.serv.entity.system.UserEntity;
import org.yzbdl.lanius.orchestrate.serv.entity.system.UserOrgEntity;
import org.yzbdl.lanius.orchestrate.serv.entity.system.UserRoleEntity;
import org.yzbdl.lanius.orchestrate.serv.enums.UserStatusEnum;
import org.yzbdl.lanius.orchestrate.serv.mapper.system.OrgMapper;
import org.yzbdl.lanius.orchestrate.serv.mapper.system.UserMapper;
import org.yzbdl.lanius.orchestrate.serv.mapper.system.UserOrgMapper;
import org.yzbdl.lanius.orchestrate.serv.mapper.system.UserRoleMapper;
import org.yzbdl.lanius.orchestrate.serv.service.system.UserService;
import org.yzbdl.lanius.orchestrate.serv.utils.CurrentUserUtil;
import org.yzbdl.lanius.orchestrate.serv.vo.system.NickNameVo;
import org.yzbdl.lanius.orchestrate.serv.vo.system.UserVo;
import org.yzbdl.lanius.orchestrate.common.base.entity.IdFieldEntity;
import org.yzbdl.lanius.orchestrate.common.exception.runtime.BusinessException;
import org.yzbdl.lanius.orchestrate.common.utils.BcryptEncoderUtil;
import org.yzbdl.lanius.orchestrate.common.utils.SpecialCharacterUtil;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户服务实现
 *
 * @author chenjunhao
 * @date 2022-04-07 14:14
 */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {


    @Autowired
    UserOrgMapper userOrgMapper;
    @Autowired
    UserRoleMapper userRoleMapper;
    @Autowired
    OrgMapper orgMapper;

    /**
     * 用户列表
     * @param userListDto 用户查询条件
     * @param page 分页内容
     * @return 用户分页列表
     */
    @Override
    public Page<UserVo> listUserPage(UserListDto userListDto, Page<UserVo> page){
        LambdaQueryWrapper<UserEntity> queryWrapper = new QueryWrapper<UserEntity>().lambda()
                .like(StringUtils.isNotEmpty(userListDto.getNickName()),UserEntity::getNickName, SpecialCharacterUtil.escapeStr(userListDto.getNickName()))
                .like(StringUtils.isNotEmpty(userListDto.getUserName()),UserEntity::getUsername,SpecialCharacterUtil.escapeStr(userListDto.getUserName()));
        List<UserVo> userVos = baseMapper.queryUserVoByOrgId(
                                CurrentUserUtil.getCurrentUserOrgId(),
		        (page.getCurrent()-1)*page.getSize(),
	                            page.getSize(),
                                queryWrapper);
        page.setTotal(baseMapper.selectCount(queryWrapper));
        page.setRecords(userVos);
        page.setTotal(baseMapper.countUserVoByOrgId(CurrentUserUtil.getCurrentUserOrgId(),queryWrapper));
        return page;
    }

    /**
     * 用户管理员查询用户
     * @param managerUserQueryDto 管理员查询条件
     * @param page 分页
     * @return 用户列表
     */
    @Override
    public Page<UserEntity> listUserPage(ManagerUserQueryDto managerUserQueryDto,Page<UserEntity> page){
        return baseMapper.queryUserByOrgId(managerUserQueryDto.getOrgId(),page,new LambdaQueryWrapper<>());
    }

    /**
     * 该组织是否存在用户
     * @param orgId 组织id
     * @return 布尔值
     */
    @Override
    public boolean isExistUserByOrgId(Long orgId){
        return Optional.ofNullable(baseMapper.getFirstUserIdByOrgId(orgId)).isPresent();
    }

    /**
     * 保存用户角色
     * @param roleIds 角色id列表
     * @param userId 用户id
     * @return 更改行数
     */
    @Override
    public int saveUserRoles(List<Long> roleIds, Long userId){
        roleIds = null==roleIds?new ArrayList<>():roleIds;
        QueryWrapper<UserRoleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UserRoleEntity::getUserId,userId);
        userRoleMapper.delete(queryWrapper);
        if(roleIds.size()==0){
            return 0;
        }
        List<UserRoleEntity> userRoleEntities = roleIds.stream()
                .map(m->
                        UserRoleEntity.builder()
                                .userId(userId)
                                .roleId(m)
                                .build()
                ).collect(Collectors.toList());
        return userRoleMapper.insertBatch(userRoleEntities);
    }

    /**
     * 添加用户
     * @param userInsertParamDto 用户参数模型
     * @return 用户实体
     */
    @Override
    public UserEntity insertUser(UserInsertParamDto userInsertParamDto){
        UserEntity existUser = getUserByUserName(userInsertParamDto.getUserName());
        if(null!=existUser){
            throw new BusinessException("重复的用户名！");
        }
        UserEntity userEntity = UserEntity.builder()
                .userName(userInsertParamDto.getUserName())
                .nickName(userInsertParamDto.getNickName())
                .password(BcryptEncoderUtil.encode(userInsertParamDto.getPassword()))
                .status(UserStatusEnum.NORMAL.getCode())
                .deleted(false)
                .build();
        save(userEntity);
        saveUserRoles(userInsertParamDto.getRoleIds(),userEntity.getId());
        return userEntity;
    }

    /**
     * 给组织添加用户
     * 普通用户添加不需要组织参数，这个地方仅仅是给管理员服务的
     * @param userInsertParamDto 组织对象
     * @param orgId 组织Id
     * @param orgChief 是否是组织负责人（目前超级管理员创建的用户都是组织领袖）
     * @return 用户实体
     */
    @Override
    public UserEntity insertUser(UserInsertParamDto userInsertParamDto, Long orgId, boolean orgChief){
        UserEntity user = insertUser(userInsertParamDto);
        if(null!=user.getId()){
            UserOrgEntity userOrgEntity = UserOrgEntity.builder()
                    .orgId(orgId)
                    .userId(user.getId())
                    .orgChief(orgChief)
                    .build();
            userOrgMapper.insert(userOrgEntity);
        }
        return user;
    }

    /**
     * 更新用户信息
     * @param userUpdateParamDto 用户更新参数
     * @return 成功与否
     */
    @Override
    public boolean updateUser(UserUpdateParamDto userUpdateParamDto){
        Optional.ofNullable(getById(userUpdateParamDto.getId())).orElseThrow(()->new BusinessException("没有找到该用户，请检查id是否出错！"));
        saveUserRoles(userUpdateParamDto.getRoleIds(),userUpdateParamDto.getId());
        if(userUpdateParamDto.getChief()!=null){
            LambdaQueryWrapper<UserOrgEntity> userOrgEntityQuery = new LambdaQueryWrapper<UserOrgEntity>()
                    .eq(UserOrgEntity::getUserId,userUpdateParamDto.getId()).eq(UserOrgEntity::getOrgId,CurrentUserUtil.getCurrentUserOrgId());
            UserOrgEntity userOrgEntity = userOrgMapper.selectOne(userOrgEntityQuery);
            if(userOrgEntity!=null){
                userOrgEntity.setOrgChief(userUpdateParamDto.getChief());
                userOrgMapper.updateById(userOrgEntity);
            }
        }
        return update(new LambdaUpdateWrapper<UserEntity>()
                .eq(IdFieldEntity::getId,userUpdateParamDto.getId())
                .set(StringUtils.isNotEmpty(userUpdateParamDto.getNickName()),UserEntity::getNickName,userUpdateParamDto.getNickName())
        );
    }

    /**
     * 通过用户名称获取实体
     * @param userName 用户名称
     * @return 用户实体
     */
    private UserEntity getUserByUserName(String userName) {
        return baseMapper.selectOne(
                new LambdaQueryWrapper<UserEntity>()
                    .eq(UserEntity::getUsername, userName)
        );
    }


    /**
     * 重置密码
     * @param userId 用户id
     * @return 新的密码
     */
    @Override
    public String resetPassword(Long userId){
        String newPassword = RandomStringUtils.randomAlphanumeric(6)+"_1Az";
        update(new LambdaUpdateWrapper<UserEntity>()
                .eq(UserEntity::getId,userId)
                .set(UserEntity::getPassword, BcryptEncoderUtil.encode(newPassword))
        );
        return newPassword;
    }

//    private String encodePassword(String psw){
//        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
//        return encoder.encode(psw);
//    }

    /**
     * 设置用户状态
     * @param status 状态值
     * @param userId 用户ID
     * @return 布尔值
     */
    @Override
    public Boolean setUserState(int status, Long userId){
        return update(
                new LambdaUpdateWrapper<UserEntity>()
                    .eq(UserEntity::getId,userId)
                        .set(UserEntity::getStatus,status)
        );
    }

    /**
     * 通过id列表找到对应的昵称
     * @param ids id集合
     * @return 包含nickname和id的对象集合
     */
    @Override
    public List<NickNameVo> listNickNamesByIds(List<Long> ids){
        return ids!=null&&!ids.isEmpty()?
                list(
                    new LambdaQueryWrapper<UserEntity>()
                        .in(IdFieldEntity::getId,ids)
                        .select(IdFieldEntity::getId,UserEntity::getNickName)
                ).stream()
                .map(NickNameVo::new)
                .collect(Collectors.toList()):
                new ArrayList<>();
    }

    /**
     * 删除用户
     * @param id 用户id
     * @return 更改行数
     */
    @Override
    public int deleteUserById(Long id,Long orgId){
        userOrgMapper.delete(new LambdaQueryWrapper<UserOrgEntity>()
            .eq(UserOrgEntity::getUserId,id).eq(UserOrgEntity::getOrgId,orgId)
        );
        boolean userOrgEntityExist = userOrgMapper.selectCount(new LambdaQueryWrapper<UserOrgEntity>().eq(UserOrgEntity::getUserId,id))>0;
        if(!userOrgEntityExist){
            return baseMapper.deleteById(id);
        }
        return 0;
    }

    /**
     * 通过用户名模糊查询用户列表
     * @param userName 用户名
     * @return 用户列表
     */
    @Override
    public List<UserEntity> listUserByUserName(String userName){
        return baseMapper.selectList(new LambdaQueryWrapper<UserEntity>().like(UserEntity::getUsername,userName));
    }


    /**
     * 判断该id是否是有效的用户
     * @param userId 用户id
     * @return 布尔值
     */
    @Override
    public boolean isExistUserById(Long userId){
        return baseMapper.selectById(userId)!=null;
    }

}
